<?php

namespace Game\Logic;

use Common\Logic\BaseLogic;

class WxPayLogic extends BaseLogic
{
    private $appid = 'wxc5feec52737006cd';
    private $appsecret = 'df80f11ec7007ddb00501ab438ee3c02';
    private $mchid = '1530168081';
    private $key = '08EB8031C19D44B1A233208C7A4B8691';

    public function _initialize()
    {
        $this->appid = 'wxc5feec52737006cd'; // * APPID：绑定支付的APPID（必须配置，开户邮件中可查看）
            $this->mchid = '1530168081'; // * MCHID：商户号（必须配置，开户邮件中可查看）
            $this->key = '08EB8031C19D44B1A233208C7A4B8691'; // KEY：商户支付密钥，参考开户邮件设置（必须配置，登录商户平台自行设置）
            $this->appsecret = 'df80f11ec7007ddb00501ab438ee3c02'; // 公众帐号secert（仅JSAPI支付的时候需要配置)，
    }

    //企业付款调用该方法
    public function trans($openID, $money, $nickname = '')
    {
        $params = array(
            'partner_trade_no' => $this->createPayid(), //生成订单号
            'openid' => $openID,
            'check_name' => 'NO_CHECK',
            'amount' => $money,
            'desc' => $nickname.'余额提现',
        );

        //证书路径
        $apicent_cert = WEB_PATH.'/paypem/apiclient_cert.pem';
        $apiclient_key = WEB_PATH.'/pay/apiclient_key.pem';

        $res = $this->payToUser($params, $apicent_cert, $apiclient_key);
        if ('SUCCESS' == $res->result_code) {
            return true; //转账成功
        } else {
            $return_message = (string) $res->err_code_des;

            return $return_message;
        }
    }

    /**
     *  array转xml.
     */
    public function arrayToXml($arr)
    {
        $xml = '<xml>';
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= '<'.$key.'>'.$val.'</'.$key.'>';
            } else {
                $xml .= '<'.$key.'><![CDATA['.$val.']]></'.$key.'>';
            }
        }
        $xml .= '</xml>';

        return $xml;
    }

    public function createNoncestr($length = 15)
    {
        $chars = '01234567890123456789';
        $str = '';
        for ($i = 0; $i < $length; ++$i) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }

        return $str;
    }

    /**
     *   作用：使用证书，以post方式提交xml到对应的接口url.
     */
    public function postXmlSSLCurl($xml, $url, $second, $cert, $key)
    {
        $ch = curl_init();
        //超时时间
        curl_setopt($ch, CURLOPT_TIMEOUT, $second ? $second : $this->timeout);

        //这里设置代理，如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, false);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        //设置证书
        //使用证书：cert 与 key 分别属于两个.pem文件
        //默认格式为PEM，可以注释
        curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
        curl_setopt($ch, CURLOPT_SSLCERT, $cert);
        //默认格式为PEM，可以注释
        curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
        curl_setopt($ch, CURLOPT_SSLKEY, $key);

        //curl_setopt ($ch, CURLOPT_CAINFO, $ca);
        //post提交方式
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        $data = curl_exec($ch);

        //返回结果
        if ($data) {
            curl_close($ch);
            //file_put_contents("./nimamama",$data);
                $restran = simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA); //解析XML到对象
                //$restran = json_decode($restran,true);
                return $restran;
        } else {
            $error = curl_errno($ch);
            echo "curl出错，错误码:$error".'<br>';
            curl_close($ch);

            return false;
        }
    }

    //生成订单号(最好在其它业务里生成该订单号,传到该类需要的函数中,Powered BY UNIX8.NET)
    public function createPayid()
    {
        return date('Ymdhis', time()).substr(floor(microtime() * 1000), 0, 1).rand(0, 9);
    }

    //企业向个人付款
    public function payToUser($params, $apicent_cert, $apiclient_key)
    {
        $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';

        //检测必填参数
        if (null == $params['partner_trade_no']) {
            exit('退款申请接口中，缺少必填参数partner_trade_no！'.'<br>');
        } elseif (null == $params['openid']) {
            exit('退款申请接口中，缺少必填参数openid！'.'<br>');
        } elseif (null == $params['check_name']) {             //NO_CHECK：不校验真实姓名 FORCE_CHECK：强校验真实姓名（未实名认证的用户会校验失败，无法转账）OPTION_CHECK：针对已实名认证的用户才校验真实姓名（未实名认证用户不校验，可以转账成功）
            exit('退款申请接口中，缺少必填参数check_name！'.'<br>');
        } elseif (('FORCE_CHECK' == $params['check_name'] or 'OPTION_CHECK' == $params['check_name']) && (null == $params['re_user_name'])) {  //收款用户真实姓名。
            exit('退款申请接口中，缺少必填参数re_user_name！'.'<br>');
        } elseif (null == $params['amount']) {
            exit('退款申请接口中，缺少必填参数amount！'.'<br>');
        } elseif (null == $params['desc']) {
            exit('退款申请接口中，缺少必填参数desc！'.'<br>');
        }

        $params['mch_appid'] = $this->appid; //公众账号ID
        $params['mchid'] = $this->mchid; //商户号
        $params['nonce_str'] = $this->createNoncestr(); //随机字符串
        $params['spbill_create_ip'] = '::1' == $_SERVER['REMOTE_ADDR'] ? '192.127.1.1' : $_SERVER['REMOTE_ADDR']; //获取IP

        $params['sign'] = $this->getSign($params); //获取签名

        $xml = $this->arrayToXml($params);

        return $this->postXmlSSLCurl($xml, $url, false, $apicent_cert, $apiclient_key);
    }

    public function formatBizQueryParaMap($paraMap, $urlencode)
    {
        $buff = '';
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if ($urlencode) {
                $v = urlencode($v);
            }
            $buff .= $k.'='.$v.'&';
        }
        $reqPar;
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }

        return $reqPar;
    }

    /**
     * 	作用：生成签名.
     */
    public function getSign($Obj)
    {
        foreach ($Obj as $k => $v) {
            $Parameters[$k] = $v;
        }
        //签名步骤一：按字典序排序参数
        ksort($Parameters);
        $String = $this->formatBizQueryParaMap($Parameters, false);
        //签名步骤二：在string后加入KEY
        $String = $String.'&key='.$this->key;
        //签名步骤三：MD5加密
        $String = md5($String);
        //签名步骤四：所有字符转为大写
        $result_ = strtoupper($String);

        return $result_;
    }
}
